#include "tests.h"

TEST(ArrayTest, DefaultConstructor) {
  s21::array<int, 5> arr;

  EXPECT_EQ(arr.size(), 5);
  for (size_t i = 0; i < arr.size(); ++i) {
    EXPECT_EQ(arr[i], 0);
  }
}

TEST(ArrayTest, SmallInitListConstructor) {
  s21::array<int, 5> arr = {1, 2, 3, 4};

  EXPECT_EQ(arr.size(), 5);
  EXPECT_EQ(arr[3], 4);
  EXPECT_EQ(arr[4], 0);
}

TEST(ArrayTest, BigInitListConstructor) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5, 6, 7};

  EXPECT_EQ(arr.size(), 5);
  EXPECT_EQ(arr[3], 4);
  EXPECT_EQ(arr[4], 5);
}

TEST(ArrayTest, CopyConstructor) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  s21::array<int, 5> copy(arr);

  EXPECT_EQ(copy.size(), 5);
  for (size_t i = 0; i < arr.size(); ++i) {
    EXPECT_EQ(copy[i], arr[i]);
  }
}

TEST(ArrayTest, MoveConstructor) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  s21::array<int, 5> dist(std::move(arr));

  EXPECT_EQ(dist.size(), 5);
  EXPECT_EQ(dist[3], 4);
  EXPECT_EQ(dist[4], 5);
}

TEST(ArrayTest, CopyAssignmentOperator) {
  s21::array<int, 5> arr1 = {1, 2, 3, 4, 5};
  s21::array<int, 5> arr2 = {6, 7, 8, 9, 0};

  arr1 = arr2;

  EXPECT_EQ(arr1[1], 7);
  EXPECT_EQ(arr1[4], 0);
}

TEST(ArrayTest, MoveAssignmentOperator) {
  s21::array<int, 5> arr1 = {1, 2, 3, 4, 5};
  s21::array<int, 5> arr2 = {6, 7, 8, 9, 0};

  arr1 = std::move(arr2);

  EXPECT_EQ(arr1[0], 6);
  EXPECT_EQ(arr1[3], 9);
}

TEST(ArrayTest, Begin) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  auto it = arr.begin();
  *it = 10;

  EXPECT_EQ(arr[0], 10);
}

TEST(ArrayTest, End) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  auto it = std::prev(arr.end());

  EXPECT_EQ(*it, 5);
}

TEST(ArrayTest, CBegin) {
  const s21::array<int, 4> arr = {1, 2, 3, 4};

  auto it = arr.cbegin();

  EXPECT_EQ(*it, 1);
}

TEST(ArrayTest, CEnd) {
  const s21::array<int, 4> arr = {1, 2, 3, 4};

  auto it = std::prev(arr.cend());

  EXPECT_EQ(*it, 4);
}

TEST(ArrayTest, DataTest) {
  s21::array<int, 3> arr = {1, 2, 3};

  int* q = arr.data();
  q[1] = 8;

  EXPECT_EQ(arr[1], 8);
}

TEST(ArrayTest, At_ValidIndex) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.at(2);

  EXPECT_EQ(value, 3);
}

TEST(ArrayTest, At_OutOfBounds) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  EXPECT_THROW(arr.at(7), std::out_of_range);
}

TEST(ArrayTest, ConstAt_ValidIndex) {
  const s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.at(3);
  EXPECT_EQ(value, 4);
}

TEST(ArrayTest, ConstAt_OutOfBounds) {
  const s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  EXPECT_THROW(arr.at(8), std::out_of_range);
}

TEST(ArrayTest, OperatorBracket) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  arr[2] = 7;

  EXPECT_EQ(arr[2], 7);
}

TEST(ArrayTest, ConstOperatorBracket) {
  const s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  EXPECT_EQ(arr[4], 5);
}

TEST(ArrayTest, Front) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.front();

  EXPECT_EQ(value, 1);
}

TEST(ArrayTest, Back) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.back();

  EXPECT_EQ(value, 5);
}

TEST(ArrayTest, ConstFront) {
  const s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.front();

  EXPECT_EQ(value, 1);
}

TEST(ArrayTest, ConstBack) {
  const s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  int value = arr.back();

  EXPECT_EQ(value, 5);
}

TEST(ArrayTest, Empty_EmptyArray) {
  s21::array<int, 0> arr;

  EXPECT_TRUE(arr.empty());
  EXPECT_EQ(arr.begin(), arr.end());
}

TEST(ArrayTest, Empty_NonEmptyArray) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  EXPECT_FALSE(arr.empty());
}

TEST(ArrayTest, Size_EmptyArray) {
  s21::array<int, 0> arr;

  EXPECT_EQ(arr.size(), 0);
  EXPECT_EQ(arr.begin(), arr.end());
}

TEST(ArrayTest, Size_NonEmptyArray) {
  s21::array<int, 5> arr = {1, 2, 3, 4, 5};

  EXPECT_EQ(arr.size(), 5);
}

TEST(ArrayTest, MaxSize) {
  s21::array<int, 5> arr;

  EXPECT_EQ(arr.max_size(), 5);
}

TEST(ArrayTest, Swap) {
  s21::array<int, 5> arr1 = {1, 2, 3, 4, 5};
  s21::array<int, 5> arr2 = {6, 7, 8, 9, 0};

  arr1.swap(arr2);

  EXPECT_EQ(arr1[2], 8);
  EXPECT_EQ(arr1[4], 0);
  EXPECT_EQ(arr2[3], 4);
  EXPECT_EQ(arr2[4], 5);
}

TEST(ArrayTest, Fill) {
  s21::array<int, 5> arr;

  arr.fill(9);

  for (size_t i = 0; i < arr.size(); ++i) {
    EXPECT_EQ(arr[i], 9);
  }
}